//----------------------------------------------------------------------------------------------
//	Filename:	SegmentsGraph.h
//	Author:		Sandro Spina
//	Date:		27/01/2013
//----------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------
#pragma once

#include "StructureGraphsForge.h"
#include "ObjStructureGraph.h"

using namespace Illumina::Core;

StructureGraphsForge::StructureGraphsForge()
{
	nodeID = new ::UniqueID();		
}

//Simple Structure Graph Forges
ObjStructureGraph * StructureGraphsForge::ForgeNullGraph() 
{
	ObjStructureGraph * structure = new ObjStructureGraph();
	ObjStructureGraph::Node * initial = CreateNewNode("initial", ObjStructureGraph::nodetype::accepting);
	structure->SetInitialNodeId(initial->id);
	structure->AddNode(initial);		
	return structure;
}

ObjStructureGraph * StructureGraphsForge::ForgeStairsStructureGraph()
{
	ObjStructureGraph * structure = new ObjStructureGraph();
	ObjStructureGraph::Node * initial = CreateNewNode("initial", ObjStructureGraph::nodetype::accepting);
	structure->SetInitialNodeId(initial->id);
	structure->AddNode(initial);

	ObjStructureGraph::EdgeStats * init_init_0 = new ObjStructureGraph::EdgeStats();		
	init_init_0->dot = 0;
	init_init_0->epsilon = 0.15f;

	ObjStructureGraph::EdgeStats * init_init_1 = new ObjStructureGraph::EdgeStats();		
	init_init_1->dot = 1;
	init_init_1->epsilon = 0.15f;

	initial->edges->push_back(new std::pair<ObjStructureGraph::EdgeStats*, ObjStructureGraph::Node*>(init_init_1, initial));			//Choose 0 deg option first		
	initial->edges->push_back(new std::pair<ObjStructureGraph::EdgeStats*, ObjStructureGraph::Node*>(init_init_0, initial));			//Choose 90 deg option next
		
	return structure;
}

ObjStructureGraph * StructureGraphsForge::Forge2orMoreStairsStructureGraph() 	
{
	ObjStructureGraph * structure = new ObjStructureGraph();		
	ObjStructureGraph::Node * initial = CreateNewNode("initial", ObjStructureGraph::nodetype::rejecting);
	structure->SetInitialNodeId(initial->id);
	structure->AddNode(initial);
		
	ObjStructureGraph::Node * s1 = CreateNewNode("s1", ObjStructureGraph::nodetype::rejecting);
	ObjStructureGraph::Node * s2 = CreateNewNode("s2", ObjStructureGraph::nodetype::accepting);
	structure->AddNode(s1);
	structure->AddNode(s2);
				
	ObjStructureGraph::EdgeStats * init_init = new ObjStructureGraph::EdgeStats();		
	init_init->dot = 1;
	init_init->epsilon = 0.15f;

	ObjStructureGraph::EdgeStats * init_s1 = new ObjStructureGraph::EdgeStats();		
	init_s1->dot = 0;
	init_s1->epsilon = 0.15f;
	//init_s1->actions = std::vector<ObjStructureGraph::action>();
	init_s1->actions.push_back(ObjStructureGraph::action::add_direction);
	init_s1->actions.push_back(ObjStructureGraph::action::transition_count);

	initial->edges->push_back(new std::pair<ObjStructureGraph::EdgeStats*, ObjStructureGraph::Node*>(init_init, initial));		//dot product = 1
	initial->edges->push_back(new std::pair<ObjStructureGraph::EdgeStats*, ObjStructureGraph::Node*>(init_s1, s1));			//dot product = 0	

	ObjStructureGraph::EdgeStats * s1_s1 = new ObjStructureGraph::EdgeStats();		
	s1_s1->dot = 1;
	s1_s1->epsilon = 0.15f;

	ObjStructureGraph::EdgeStats * s1_s2 = new ObjStructureGraph::EdgeStats();
	s1_s2->dot = 0;
	s1_s2->epsilon = 0.15f;
	//s1_s2->actions = std::vector<ObjStructureGraph::action>();
	s1_s2->actions.push_back(ObjStructureGraph::action::add_direction);
	s1_s2->actions.push_back(ObjStructureGraph::action::transition_count);

	s1->edges->push_back(new std::pair<ObjStructureGraph::EdgeStats*, ObjStructureGraph::Node*>(s1_s1, s1));		//dot product = 1
	s1->edges->push_back(new std::pair<ObjStructureGraph::EdgeStats*, ObjStructureGraph::Node*>(s1_s2, s2));		//dot product = 0	

	ObjStructureGraph::EdgeStats * s2_s2_0 = new ObjStructureGraph::EdgeStats();		
	s2_s2_0->dot = 0;
	s2_s2_0->epsilon = 0.15f;
	//s2_s2_0->actions = std::vector<ObjStructureGraph::action>();
	s2_s2_0->actions.push_back(ObjStructureGraph::action::add_direction);
	s2_s2_0->actions.push_back(ObjStructureGraph::action::transition_count);
		
	ObjStructureGraph::EdgeStats * s2_s2_1 = new ObjStructureGraph::EdgeStats();		
	s2_s2_1->dot = 1;
	s2_s2_1->epsilon = 0.15f;

	s2->edges->push_back(new std::pair<ObjStructureGraph::EdgeStats*, ObjStructureGraph::Node*>(s2_s2_1, s2));		//dot product = 1
	s2->edges->push_back(new std::pair<ObjStructureGraph::EdgeStats*, ObjStructureGraph::Node*>(s2_s2_0, s2));		//dot product = 0	

	return structure;
}

ObjStructureGraph * StructureGraphsForge::ForgeSimpleChairGraph() 
{
	ObjStructureGraph * structure = new ObjStructureGraph();
	ObjStructureGraph::Node * initial = CreateNewNode("initial", ObjStructureGraph::nodetype::rejecting);
	structure->SetInitialNodeId(initial->id);
	structure->AddNode(initial);					

	ObjStructureGraph::EdgeStats * init_init_0 = new ObjStructureGraph::EdgeStats();
	init_init_0->dot = 1;
	init_init_0->epsilon = 0.15f;

	ObjStructureGraph::Node * s0 = CreateNewNode("s0", ObjStructureGraph::nodetype::accepting);		
	structure->AddNode(s0);
		
	ObjStructureGraph::EdgeStats * init_s0 = new ObjStructureGraph::EdgeStats();
	init_s0->dot = 0;
	init_s0->epsilon = 0.15f;
	init_s0->actions = std::vector<ObjStructureGraph::action>();
	init_s0->actions.push_back(ObjStructureGraph::action::add_direction);
	init_s0->actions.push_back(ObjStructureGraph::action::transition_count);

	initial->edges->push_back(new std::pair<ObjStructureGraph::EdgeStats*, ObjStructureGraph::Node*>(init_init_0, initial));
	initial->edges->push_back(new std::pair<ObjStructureGraph::EdgeStats*, ObjStructureGraph::Node*>(init_s0, s0));
		
	return structure;
}

ObjStructureGraph * StructureGraphsForge::GetMultiSegmentFloorGraph() 
{
	ObjStructureGraph * structure = new ObjStructureGraph();
		
	//TODO

	return structure;
}

ObjStructureGraph::Node * StructureGraphsForge::CreateNewNode(std::string label, ObjStructureGraph::nodetype p_type)
{
	ObjStructureGraph::Node * node = new ObjStructureGraph::Node();
	node->id = nodeID->GetNext();		
	node->stats = new ObjStructureGraph::NodeStats();
	node->stats->type = p_type;
	node->stats->label = label;
	node->edges = new std::vector<std::pair<ObjStructureGraph::EdgeStats*, ObjStructureGraph::Node*>*>();
	return node;
}

//Inference Structure Graph Forges
//TODO